package com.sd365.permission.centre.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.sd365.common.core.annotation.mybatis.Pagination;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.common.advice.MyPageInfo;
import com.sd365.common.core.common.constant.EntityConsts;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.common.exception.code.BizErrorCode;
import com.sd365.common.core.common.exception.code.CommonErrorCode;
import com.sd365.common.core.common.service.AbstractBusinessService;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.core.mq.ActionType;
import com.sd365.common.util.BeanException;
import com.sd365.common.util.BeanUtil;
import com.sd365.common.util.StringUtil;
import com.sd365.permission.centre.dao.mapper.*;
import com.sd365.permission.centre.entity.*;
import com.sd365.permission.centre.pojo.dto.RoleDTO;
import com.sd365.permission.centre.pojo.dto.UserCentreDTO;
import com.sd365.permission.centre.pojo.dto.UserDTO;
import com.sd365.permission.centre.pojo.dto.pcp.PcpUserDTO;
import com.sd365.permission.centre.pojo.dto.shop.ShopBuyerDTO;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.service.UserService;
import com.sd365.permission.centre.service.util.DefaultTenant;
import com.sd365.permission.centre.service.util.Md5Utils;
import com.sd365.permission.centre.service.util.SendMQMessageUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.validation.Valid;
import java.util.Calendar;
import java.util.List;

/**
 * @ClassName UserServiceImpl
 * @Description zhb 新增接口满足BM对系统对用户中心 更新个人信息的调用 modifyUserInfoForBm
 * @Author yangshaoqi
 * @Date 2020/12/14 21:29
 * @Version 1.0
 **/
@Service
public class UserServiceImpl extends AbstractBusinessService implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private PositionMapper positionMapper;

    @Autowired
    DefaultTenant defaultTenant;

    @Autowired
    private SendMQMessageUtil sendMQMessageUtil;
    private static final Long DRIVER_ID = 1346692911269543943L;
    private static final String TABLE_NAME = "driver";


    @Override
    public Boolean add(@Valid UserDTO userDTO) {
        if (userMapper.selectByCode(userDTO.getCode()) != null || StringUtil.isEmpty(userDTO.getPassword())) {
            throw  new BusinessException(BizErrorCode.DATA_INSERT_FOUND_NO_UNIQUE_RECORD,new RuntimeException("用户重复或者密码为空"));
        }
        User user = BeanUtil.copy(userDTO, User.class);
        user.setId(idGenerator.snowflakeId());
        // 如果token为空(未登录)，使用默认的tenant数据填充
        // 如果因为注册原因有必要分离接口
        if (StringUtil.isEmpty(BaseContextHolder.getToken())) {
            defaultTenant.fillField(user);
        } else {
            // 正常加入用户走以下代码
            super.baseDataStuff4Add(user);
            super.baseDataStuffCommonPros(user);
            user.setVersion(EntityConsts.INITIAL_VERSION);
        }
        user.setPassword(Md5Utils.digestHex(user.getPassword()));

        // 一下代码有必要重构 如何耦合了driver？？？
        // TODO 相应系统做重构不允许 用户中心偶合driver synchronizeAddUser(user);
        // 将用户和角色全部插入表
        userMapper.insert(user);
        UserRole userRole = new UserRole();
        List<RoleDTO> roleList = userDTO.getRoleList();
        roleList.stream().forEach(roleDTO -> {
            userRole.setId(idGenerator.snowflakeId());
            userRole.setVersion(1L);
            super.baseDataStuff4Add(userRole);
            super.baseDataStuffCommonPros(userRole);
            userRole.setUserId(user.getId());
            userRole.setRoleId(roleDTO.getId());
            userRoleMapper.insert(userRole);
        });
            // 多个系统都更新用户
        sendMQMessageUtil.fanoutSendMessage(ActionType.INSERT, "", "", user);
        return true;
    }

    /**
     * 通过mq同步用户到其他系统
     * @param user 当前操作的用户
     */
    private void synchronizeAddUser(User user) {
        if (user.getPositionId().compareTo(DRIVER_ID) == 0) {
            Driver driver = new Driver();
            driver.setId(user.getId());
            driver.setBirthday(user.getBirthday());
            driver.setCode(user.getCode());
            driver.setName(user.getName());
            driver.setVersion(1L);
            driver.setTel(user.getTel());
            driver.setSex(user.getSex());
            super.baseDataStuff4Add(driver);
            sendMQMessageUtil.SendMessage(ActionType.INSERT, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, driver);
        }
    }

    @Override
    public Boolean remove(Long id, Long version) {
        try {
            User user = userMapper.selectByPrimaryKey(id);
            Boolean flag = false;
            if (userRoleMapper.selectByUserId(id) != null) {
                userRoleMapper.deleteAllByUserID(id);
                Example example = new Example(User.class);
                example.createCriteria().andEqualTo("id", id).andEqualTo("version", version);
                example.createCriteria().andEqualTo("id", id).andEqualTo("version", version);
                flag = userMapper.deleteByExample(example) > 0;

            }
            if (userRoleMapper.selectByUserId(id) == null) {
                Example example = new Example(User.class);
                example.createCriteria().andEqualTo("id", id).andEqualTo("version", version);
                flag = userMapper.deleteByExample(example) > 0;

            }
            synchronizeRemoveUser(user, user.getId(), user.getVersion());
            return flag;
        } catch (BeanException ex) {
            throw new BusinessException(CommonErrorCode.SYSTEM_DB_CONSTRAINT_EXCEPTION, ex);
        }
    }

    private void synchronizeRemoveUser(User user, Long id2, Long version2) {
        if (user.getPositionId().compareTo(DRIVER_ID) == 0) {
            Driver driver = new Driver();
            driver.setId(id2);
            driver.setVersion(version2);
            sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, driver);
        }
    }

    @Override
    public Boolean modify(UserDTO userDTO) {
        try {

            User user = BeanUtil.copy(userDTO, User.class);
            User orginUser = userMapper.selectByPrimaryKey(user.getId());
            boolean flag = false;
            if (!StringUtil.isEmpty(user.getPassword())) {
                //原密码新新密码一致不做更新
                if (user.getPassword().equals(orginUser.getPassword())) {
                    user.setPassword(null);
                } else {
                    //否则更新
                    /**
                     * 郑黄彬20221201更新
                     * 由于bm传来的userDTO只有加密后的password，所以即使要更新密码也不能加密
                     * 另:由于现在门户个人中心界面不再能修改个人密码，门户所有个人密码的修改调用的是pc的updatePassword方法，
                     * 建议是将该方法的更新密码部分删除
                     */
                    user.setPassword(Md5Utils.digestHex(user.getPassword()));
                }
            }
            if (userDTO.getRoleList() == null) {
                flag = userMapper.updateByPrimaryKeySelective(user) > 0;
            } else {

                userMapper.updateByPrimaryKeySelective(user);
                UserRole userRole = new UserRole();
                List<RoleDTO> roleList = userDTO.getRoleList();
                if (roleList != null && !roleList.isEmpty()) {
                    userRoleMapper.deleteAllByUserID(userDTO.getId());
                    for (RoleDTO role : roleList) {
                        userRole.setId(idGenerator.snowflakeId());
                        userRole.setVersion(1L);
                        super.baseDataStuff4Add(userRole);
                        super.baseDataStuffCommonPros(userRole);
                        userRole.setUserId(user.getId());
                        userRole.setRoleId(role.getId());
                        userRoleMapper.insert(userRole);
                    }
                }
                flag = true;
            }
            if ((user.getPositionId() != null) && (orginUser.getPositionId().compareTo(DRIVER_ID) == 0) && (user.getPositionId().compareTo(DRIVER_ID) != 0)) {
                Driver driver = new Driver();
                driver.setId(user.getId());
                driver.setVersion(user.getVersion());
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, driver);
            }
            if ((user.getPositionId() != null) && (orginUser.getPositionId().compareTo(DRIVER_ID) != 0) && (user.getPositionId().compareTo(DRIVER_ID) == 0)) {
                Driver driver = new Driver();
                driver.setId(user.getId());
                driver.setBirthday(user.getBirthday());
                driver.setCode(user.getCode());
                driver.setName(user.getName());
                driver.setVersion(user.getVersion());
                driver.setTel(user.getTel());
                driver.setSex(user.getSex());
                driver.setCarrierId(1349165587770769408L);
                super.baseDataStuff4Updated(driver);
                sendMQMessageUtil.SendMessage(ActionType.INSERT, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, driver);
            }
            if ((user.getPositionId() != null) && (user.getPositionId().compareTo(orginUser.getPositionId()) == 0) && (orginUser.getPositionId().compareTo(DRIVER_ID) == 0)) {
                Driver driver = new Driver();
                driver.setId(user.getId());
                driver.setBirthday(user.getBirthday());
                driver.setCode(user.getCode());
                driver.setName(user.getName());
                driver.setVersion(1L);
                driver.setTel(user.getTel());
                driver.setSex(user.getSex());
                driver.setCarrierId(1349165587770769408L);
                super.baseDataStuff4Updated(driver);
                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, driver);
            }
            return flag;
        } catch (BeanException ex) {
            throw new BusinessException(CommonErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        }
    }

    @Override
    public Boolean modifyUserInfo(UserCentreDTO userCentreDTO) {
        try {
            User user = BeanUtil.copy(userCentreDTO, User.class);
            user.setPassword(null);
            return userMapper.updateByPrimaryKeySelective(user) >= 0;
        } catch (BeanException ex) {
            throw new BusinessException(CommonErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        }
    }


    @Override
    public Boolean modifyUserInfoForBm(UserCentreDTO userCentreDTO) {
        try {


            User user = BeanUtil.copy(userCentreDTO, User.class);
            User orginUser = userMapper.selectByPrimaryKey(user.getId());
            if (!StringUtil.isEmpty(user.getPassword())) {
                //原密码新新密码一致不做更新
                String originPwd = Md5Utils.digestHex(user.getPassword());
                if (originPwd.equals(orginUser.getPassword())) {
                    user.setPassword(null);
                } else {
                    /**
                     * 否则更新
                     * 郑黄彬20221201更新
                     * 由于bm传来的userDTO只有加密后的password，所以即使要更新密码也不能加密
                     * 另:由于现在门户个人中心界面不再能修改个人密码，门户所有个人密码的修改调用的是pc的updatePassword方法，
                     * 建议是将该方法的更新密码部分删除
                     */
                    user.setPassword(originPwd);
                }
            }
            return userMapper.updateByPrimaryKeySelective(user) >= 0;

        } catch (BeanException ex) {
            throw new BusinessException(CommonErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        }
    }

    @Override
    public Boolean modifyWithNewRole(@NonNull UserDTO[] userDTOS) {
        if (CollectionUtils.isEmpty(userDTOS[0].getRoleList()) ) {
            throw new BusinessException(BizErrorCode.PARAM_VALID_FIELD_VIOLITE_RULE,"角色id列表为空");
        } else {
            for (UserDTO userDTO : userDTOS) {
                UserRole userRole = new UserRole();
                // 采用野蛮策略直接删除了，如果需要判断后删除不存在的则逻辑较为复杂
                userRoleMapper.deleteAllByUserID(userDTO.getId());
                List<RoleDTO> roleList = userDTO.getRoleList();
                for (RoleDTO roleDTO : roleList) {
                    userRole.setId(idGenerator.snowflakeId());
                    userRole.setVersion(1L);
                    super.baseDataStuff4Updated(userRole);
                    super.baseDataStuffCommonPros(userRole);
                    userRole.setUserId(userDTO.getId());
                    userRole.setRoleId(roleDTO.getId());
                    userRoleMapper.insert(userRole);
                }
            }
            return true;
        }


    }

    @Pagination
    @Override
    public List<User> commonQuery(UserQuery userQuery) {
        if (userQuery == null) {
            throw new BusinessException(BizErrorCode.PARAM_VALID_FIELD_REQUIRE, new Exception("commonQuery 参数不能为null"));
        }
        try {
            User user = new User();
            user.setName(userQuery.getName());
            user.setCode(userQuery.getCode());
            user.setTel(userQuery.getTel());
            user.setPositionId(userQuery.getPositionId());
            user.setDepartmentId(userQuery.getDepartmentId());

            if (userQuery.getRoleId() == null) {
                List<User> userList = userMapper.commonQuery(user);
                for (User currentUser : userList) {
                    currentUser.setRoleList(roleMapper.selectRoleByUserId(currentUser.getId()));
                    currentUser.setPassword(Md5Utils.digestHex(currentUser.getPassword()));
                }
                Page page = (Page) userList;
                BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
                return userList;
            } else {
                List<User> users = userMapper.commonByQueryRoleId(user, userQuery.getRoleId());

                for (User currentUser : users) {
                    currentUser.setRoleList(roleMapper.selectRoleByUserId(currentUser.getId()));
                    currentUser.setPassword(Md5Utils.digestHex(currentUser.getPassword()));
                }
                Page page = (Page) users;
                BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
                return users;
            }

        } catch (BeanException ex) {
            throw new BusinessException(CommonErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        }
    }

    @Override
    public User queryById(Long id) {
        User user = userMapper.selectById(id);

        if (user == null) {
            return null;
        }
        // 查询信息对密码不再进行加密
        // user.setPassword(Md5Utils.digestHex(user.getPassword()));
        List<Role> roles = roleMapper.selectRoleByUserId(id);
        user.setRoleList(roles);
        return user;
    }

    @Override
    public List<Role> queryAllRole() {
        return roleMapper.selectAll();
    }

    @Override
    public List<Department> queryAllDepartment() {
        return departmentMapper.selectAll();
    }

    @Override
    public List<Position> queryAllPosition() {
        return positionMapper.selectAll();
    }

    @Override
    public Boolean batchUpdate(UserDTO[] userDTOS) {

        Assert.noNullElements(userDTOS, "更新数组不能为空");
        for (UserDTO userDTO : userDTOS) {
            User user = BeanUtil.copy(userDTO, User.class);
            int result = userMapper.updateStatus(user);
            Assert.isTrue(result > 0, "没有找到相应id更新记录");
        }
        return true;
    }

    @Override
    public Boolean batchDelete(UserDTO[] userDTOS) {
        Assert.noNullElements(userDTOS, " 批量删除数组不能为空");
        for (UserDTO userDTO : userDTOS) {
            User user = userMapper.selectByPrimaryKey(userDTO.getId());

            try {
                Boolean flag = false;
                if (userRoleMapper.selectByUserId(userDTO.getId()) != null) {
                    userRoleMapper.deleteAllByUserID(userDTO.getId());
                    Example example = new Example(User.class);
                    example.createCriteria().andEqualTo("id", userDTO.getId()).andEqualTo("version", userDTO.getVersion());
                    flag = userMapper.deleteByExample(example) > 0;
                }
                if (userRoleMapper.selectByUserId(userDTO.getId()) == null) {
                    Example example = new Example(User.class);
                    example.createCriteria().andEqualTo("id", userDTO.getId()).andEqualTo("version", userDTO.getVersion());
                    flag = userMapper.deleteByExample(example) > 0;

                }
                if (flag) {
                    synchronizeRemoveUser(user, userDTO.getId(), userDTO.getVersion());
                }

            } catch (BeanException ex) {
                throw new BusinessException(CommonErrorCode.SYSTEM_DB_CONSTRAINT_EXCEPTION, ex);
            }

        }

        return true;
    }

    @Override
    public Boolean firstStartMd5() {


        List<User> users = userMapper.selectAll();
        Example example = new Example(User.class);
        for (User user : users) {
//            User newUser = new User();
//            newUser.setId(user.getId());
//            newUser.setPassword(Md5Utils.digestHex(user.getPassword()));
//            newUser.setStatus(null);
//            example.createCriteria().andEqualTo("id", newUser.getId());
//            userMapper.updateByExampleSelective(newUser, example);
//            example.clear();
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean pcpUserRegister(List<PcpUserDTO> pcpUserDTOS) {

        try {
            pcpUserDTOS.stream().forEach(item -> {
                User user = new User();
                user.setVersion(1L);
                user.setId(item.getId());
                user.setBirthday(item.getBirthday());
                user.setCode(item.getTel());
                user.setPassword(Md5Utils.digestHex(item.getPassword()));
                user.setName(item.getName());
                user.setTenantId(1337940702788714496L);
                super.baseDataStuff4Add(user);
                super.baseDataStuffCommonPros(user);
                Boolean flag = userMapper.insert(user) > 0;
                if (flag) {
                    UserRole userRole = new UserRole();
                    userRole.setId(idGenerator.snowflakeId());
                    userRole.setUserId(user.getId());
                    userRole.setRoleId(1337645864428109824L);
                    userRole.setStatus((byte) 0);
                    userRole.setVersion(1L);
                    super.baseDataStuff4Add(userRole);
                    super.baseDataStuffCommonPros(userRole);
                    userRoleMapper.insert(userRole);
                }
            });
            return true;
        } catch (Exception e) {
            throw new BusinessException();
        }
    }

    @Override
    public Boolean pcpUserUpdate(List<PcpUserDTO> pcpUserDTOS) {

        try {
            pcpUserDTOS.stream().forEach(item -> {
                if (item.getId() != null) {
                    User user = new User();
                    user.setId(item.getId());
                    user.setPassword(Md5Utils.digestHex(item.getPassword()));
                    user.setStatus(null);
                    Example example = new Example(User.class);
                    example.createCriteria().andEqualTo("id", user.getId());
                    userMapper.updateByExampleSelective(user, example);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Deprecated
    @Override
    public Boolean updateUserLockStatus(List<PcpUserDTO> pcpUserDTOS) {

        Example example = new Example(User.class);

        try {
            for (PcpUserDTO pcpUserDTO : pcpUserDTOS) {
                User copy = BeanUtil.copy(pcpUserDTO, User.class);
                example.createCriteria().andEqualTo("id", copy.getId());
                copy.setVersion(null);
                copy.setUpdatedTime(Calendar.getInstance().getTime());
                userMapper.updateByExampleSelective(copy, example);
                example.clear();
            }
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    @Override
    public Boolean updateUserLockStatus(PcpUserDTO userDTO) {
        Example example = new Example(User.class);
        User copy = BeanUtil.copy(userDTO, User.class);
        example.createCriteria().andEqualTo("id", copy.getId());
        copy.setVersion(null);
        copy.setUpdatedTime(Calendar.getInstance().getTime());
        return userMapper.updateByExampleSelective(copy, example) > 0;
    }

    @Override
    public Boolean shopUserRegister(List<ShopBuyerDTO> shopBuyerDTOS) {
        try {
            shopBuyerDTOS.stream().forEach(item -> {
                User user = new User();
                user.setVersion(1L);
                user.setId(item.getId());
                user.setBirthday(null);
                user.setCode(item.getTel());
                user.setPassword(Md5Utils.digestHex(item.getTel()));

                user.setName(item.getName());
                user.setTenantId(1337940702788714496L);
                super.baseDataStuff4Add(user);
                super.baseDataStuffCommonPros(user);

                Boolean flag = userMapper.insert(user) > 0;
                if (flag) {
                    UserRole userRole = new UserRole();
                    userRole.setId(idGenerator.snowflakeId());
                    userRole.setUserId(user.getId());
                    userRole.setRoleId(1337645864428109824L);
                    userRole.setStatus((byte) 0);
                    userRole.setVersion(1L);
                    super.baseDataStuff4Add(userRole);
                    super.baseDataStuffCommonPros(userRole);
                    userRoleMapper.insert(userRole);
                }

            });
            return true;
        } catch (Exception e) {
            throw new BusinessException("505", "用户注册失败");
        }
    }

    @Override
    public Boolean updatePassword(UserDTO userDTO) {

        if (userDTO.getId() != null && !StringUtil.isEmpty(userDTO.getPassword())) {
            User copy = BeanUtil.copy(userDTO, User.class);
            Example example = new Example(User.class);
            example.createCriteria().andEqualTo("id", copy.getId());
            copy.setStatus(null);
            copy.setPassword(Md5Utils.digestHex(copy.getPassword()));
            return userMapper.updateByExampleSelective(copy, example) > 0;
        }
        return false;
    }

    @Override
    public User getUser(String code) {
        User user = new User();
        if (!StringUtils.isEmpty(code)) {
            Example example = new Example(User.class);
            example.createCriteria().andEqualTo("code", code);
            user = userMapper.selectOneByExample(example);
        }
        return user;
    }
}
